// i.d(t, { Q: () => OpenDeferred })

export default class OpenDeferred<T = any> {
  base: Promise<T>
  resolver: any
  rejecter: any
  _promise: OpenPromise<T>
  progressCallbacks: any[]
  constructor() {
    this.base = new Promise((resolve, reject) => {
      this.resolver = resolve
      this.rejecter = reject
    })
    this._promise = new OpenPromise(this.base, this)
    this.progressCallbacks = []
  }
  then(resolve?: any, reject?: any) {
    return this.base.then(resolve, reject)
  }
  catch(e) {
    return this.base.catch(e)
  }
  resolve(e?) {
    this.resolver(e)
    return this
  }
  reject(e?: any) {
    this.rejecter(e)
    return this
  }
  notify(e?: any) {
    for (const t of this.progressCallbacks) t(e)
  }
  progress(e) {
    return this.progressCallbacks.push(e), this
  }
  promise() {
    return this._promise
  }
  nativePromise() {
    return this.base
  }
  static resolve() {
    const e = new OpenDeferred()
    e.resolve()
    return e.promise()
  }
  static reject(e) {
    const t = new OpenDeferred()
    t.reject(e)
    return t.promise()
  }
  static all(e) {
    const t: any[] = []
    for (const i of e) i.nativePromise ? t.push(i.nativePromise()) : t.push(i)
    const i = new OpenDeferred()
    Promise.all(t).then(
      e => i.resolve(e),
      e => i.reject(e)
    )
    return i.promise()
  }
}
export class OpenPromise<T = any> {
  basePromise: Promise<T>
  baseDeferred: OpenDeferred
  constructor(basePromise: Promise<T>, baseDeferred: OpenDeferred) {
    this.basePromise = basePromise
    this.baseDeferred = baseDeferred
  }
  then(e, t) {
    this.baseDeferred.then(e, t)
    return this
  }
  catch(e) {
    this.baseDeferred.catch(e)
    return this
  }
  progress(e) {
    this.baseDeferred.progress(e)
    return this
  }
  nativePromise() {
    return this.basePromise
  }
}
